// --- Copyright (c) 2006-2008 Stefan Kyntchev ---
// This software is written and copyrighted by Stefan Kyntchev 
// and BeyondPod Team members. All rights are reserved.
// Author contact: support@beyondpod.mobi
// ------------------------------------------------------------------------
// This file is part of BeyondPod RSS Feed Reader and Podcast manager
// (www.codeplex.com/BeyondPod) 
// BeyondPod is free software: you can redistribute it and/or modify 
// it under the terms of the GNU General Public License as published by 
// the Free Software Foundation, either version 3 of the License, or 
// (at your option) any later version. 
//  
// BeyondPod is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more details. 
//  
// You should have received a copy of the GNU General Public License
// along with BeyondPod. If not, see <http://www.gnu.org/licenses/>
// ------------------------------------------------------------------------
// COPYRIGHT NOTICE: This copyright notice may NOT be removed, obscured or modified 
// without written consent from the author.
// --- End copyright notice --- 


using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using OpenNETCF.Windows.Forms;
using svs.Mobile.BeyondMedia.FeedCore;
using svs.Mobile.BeyondMedia.FeedCore.Helpers;
using svs.Mobile.BeyondMedia.FeedCore.RSS;
using svs.Mobile.BeyondMedia.FeedCore.RSS.Aggregators;
using svs.Mobile.BeyondMedia.FeedCore.RSS.Entities;
using svs.Mobile.BeyondMedia.Forms;
using svs.Mobile.BeyondMedia.Forms.Settings;
using svs.Mobile.BeyondMedia.Properties;
using svs.Mobile.BeyondMedia.UiCore;

namespace svs.Mobile.BeyondMedia.Objects
{
	internal class DelayedDeleter
	{
		private readonly Timer m_DelayedDeleteTimer = new Timer();
		private Track m_TrackToDelete;

		public DelayedDeleter()
		{
			m_DelayedDeleteTimer.Interval = 2000;
			m_DelayedDeleteTimer.Tick += DelayedDelete;
		}

		public void DeleteTrack(Track i_Track)
		{
			if (m_DelayedDeleteTimer.Enabled)
				return;

			m_TrackToDelete = i_Track;
			m_DelayedDeleteTimer.Enabled = true;
		}

		private void DelayedDelete(object sender, EventArgs e)
		{
			m_DelayedDeleteTimer.Enabled = false;
			FeedRepository.DeleteTrack(m_TrackToDelete, true);
		}
	}

	public class DelayedCommandExecutor
	{
		public delegate void CommandDelegate();

		private readonly Timer m_DelayedExecutionTimer = new Timer();
		private CommandDelegate _CommandToExecute;

		private DelayedCommandExecutor()
		{
			m_DelayedExecutionTimer.Tick += delegate
			                                	{
			                                		m_DelayedExecutionTimer.Enabled = false;
			                                		if (_CommandToExecute != null)
			                                			_CommandToExecute();
			                                	};
		}

		private static readonly DelayedCommandExecutor _Executor = new DelayedCommandExecutor();

		public static void ExecuteCommand(int delay, CommandDelegate command)
		{
			if(_Executor.m_DelayedExecutionTimer.Enabled)
				return;

			_Executor.m_DelayedExecutionTimer.Interval = delay;
			_Executor._CommandToExecute = command;
			_Executor.m_DelayedExecutionTimer.Enabled = true;
		}
	}

	internal class CommandManager
	{
		private static readonly DelayedDeleter m_DelayedDeleter = new DelayedDeleter();

		/// <summary>
		/// Subscribes for control events.
		/// </summary>
		public static void SubscribeForControlEvents()
		{
			ViewManager.Feeds.Select += OnFeedSelected;
			ViewManager.Feeds.SelectedIndexChanged += OnSelectedFeedChanged;
			ViewManager.Feeds.ReturnLongPress += OnFeedsReturnLongPress;
			ViewManager.Tracks.Select += OnTrackSelected;
			ViewManager.MediaPlayer.Navigation += OnNavigation;
			ViewManager.Tracks.Navigation += OnNavigation;
			ViewManager.Feeds.Navigation += OnNavigation;
			ViewManager.FeedContent.Navigation += OnNavigation;
			FeedRepository.RepositoryLoaded += OnRepositoryLoaded;
			ViewManager.Categories.Select += OnCategorySelected; 
		}

		private static void OnCategorySelected(FeedCategory category)
		{
			if (category != null && category != Configuration.ActiveFeedCategory)
			{
				Configuration.ActiveFeedCategory = category;
				ViewManager.Feeds.SetRootFeed(FeedRepository.RootFeed, null);
			}

			CmdGoToView(Helpers.ViewNames.Feeds);
		}

		private static void OnFeedsReturnLongPress(object sender, EventArgs e)
		{
			CmdGoToView(Helpers.ViewNames.Categories);
		}

		public static void CmdShowWhatIsNewInCurrentCategory()
		{
			var a = new CategoryAggregate(Configuration.ActiveFeedCategory);

			var f = new Feed(Guid.NewGuid(), null);
			f.FeedUrl = a.ToUrl().ToString();
			f.Name = "What is New in " + Configuration.ActiveFeedCategory.Name;
			RssFeedCache.DeleteFeedCacheFor(f);
			CmdOpenFeedBrowser(f);
		}

		#region Event Handlers

		private static void OnSelectedFeedChanged(object sender, EventArgs e)
		{
			if (ViewManager.Feeds.SelectedFeed != null)
			{
				MenuManager.WellKnownMenus[MenuManager.WellKnownMenuItems.Feed_Open].Enabled = true;
				if (ViewManager.Feeds.SelectedFeed.Tracks.Count > 0)
				{
					MenuManager.WellKnownMenus[MenuManager.WellKnownMenuItems.Feed_Open].Text = "Podcasts";
				}
				else
				{
					MenuManager.WellKnownMenus[MenuManager.WellKnownMenuItems.Feed_Open].Text = "Content";
				}
			}
			else
			{
				MenuManager.WellKnownMenus[MenuManager.WellKnownMenuItems.Feed_Open].Text = "Player";
				MenuManager.WellKnownMenus[MenuManager.WellKnownMenuItems.Feed_Open].Enabled = ViewManager.MediaPlayer.HasPlaylist;
			}
		}

		private static void OnRepositoryLoaded()
		{
			ViewManager.Tracks.Clear();
			ViewManager.MediaPlayer.ClearPlaylist();
			InitializeFeeds();
		}

		/// <summary>
		/// Tracks is the selected.
		/// </summary>
		/// <param name="aTrack">A track.</param>
		public static void OnTrackSelected(Track aTrack)
		{
			aTrack.ParentFeed.HasNewContent = false; //mark the feed as read

			if (aTrack.ParentFeed.CurrentFeedPlayer == PlayerIntegration.UseInternalPlayer)
			{
				if (aTrack.SupportedFileType)
				{
					ViewManager.MediaPlayer.PlayTracks(ViewManager.Tracks.CurrentPlaylist, aTrack);
					CmdGoToView(Helpers.ViewNames.Player);
					ViewManager.RefreshTitle();
				}
				else
				{
					if (StartExternalPlayerFor(aTrack.TrackPath))
					{
						aTrack.MarkPlayed();
						ViewManager.Tracks.SelectNextTrack();
					}
				}
			}
			else if (aTrack.ParentFeed.CurrentFeedPlayer == PlayerIntegration.UseExternalPlayerTrack)
			{
				if (StartExternalPlayerFor(aTrack.TrackPath))
				{
					aTrack.MarkPlayed();
					ViewManager.Tracks.SelectNextTrack();
				}
			}
			else
			{
				try
				{
					string playlist = FeedRepository.GeneratePlaylistFor(ViewManager.Tracks.CurrentPlaylist, aTrack,
					                                                     aTrack.ParentFeed.CurrentFeedPlayer);
					StartExternalPlayerFor(playlist);
				}
				catch (Exception ex)
				{
					MessageBoxEx.Show(string.Format(Resources.PlaylistGenerationFailedMsg, ex.Message),
					                  Resources.PlaylistGenerationFailedTitle, MessageBoxButtons.OK,
					                  MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
				}
			}
		}

		/// <summary>
		/// Feed is the selected.
		/// </summary>
		public static void OnFeedSelected(Feed aFeed, FeedViewType view)
		{
			if (aFeed != null)
			{
				//Check for Up to parent 
				if(ViewManager.Feeds.Feed.CanNavigateUp && aFeed.Equals(FeedRepository.GoUpPlaceholder))
				{
					var f = ViewManager.Feeds.Feed;
					ViewManager.Feeds.SetRootFeed(f.ParentFeed, f);
				}
				else
				{
					aFeed.ViewType = view;
					OpenDefaultFeedView(aFeed);	
				}
			}
		}


		/// <summary>
		/// Called when keyboard navigation occurs.
		/// </summary>
		/// <param name="sender">The sender.</param>
		/// <param name="i_direction">The i_direction.</param>
		public static void OnNavigation(object sender, Helpers.NavigationDirection i_direction)
		{
			if (ViewManager.CurrentViewName == Helpers.ViewNames.Player)
			{
				if (i_direction == Helpers.NavigationDirection.Back)
					CmdGoToView(Helpers.ViewNames.Feeds);
				else
				{
					NavigateToFeedContentView();
				}
			}
			else if (ViewManager.CurrentViewName == Helpers.ViewNames.Tracks || ViewManager.CurrentViewName == Helpers.ViewNames.Feeds)
			{
				if (i_direction == Helpers.NavigationDirection.Forward)
				{
					NavigateToFeedContentView();
				}
				else
				{
						if (!ViewManager.MediaPlayer.HasPlaylist)
							Helpers.Beep();
						else
							CmdGoToView(Helpers.ViewNames.Player);
				}
			}
		}

		/// <summary>
		/// Called when [before application exit].
		/// </summary>
		internal static void OnBeforeApplicationExit()
		{
			try
			{
				CmdTerminateBatchUpdate();

				Configuration.LastActiveScreen = (int) ViewManager.CurrentViewName;

				CategoryManager.Save();

				if (ViewManager.Feeds.SelectedFeed != null)
					Configuration.LastSelectedFeed = ViewManager.Feeds.SelectedFeed.ID;

				if (ViewManager.MediaPlayer.IsPlayerLoaded)
				{
					if (ViewManager.MediaPlayer.IsPlaying)
					{
						Configuration.LastPlayedTrackPath = ViewManager.MediaPlayer.CurrentTrack.TrackPath;
					}
					else
					{
						Configuration.LastPlayedTrackPath = string.Empty;
					}

					Configuration.VolumeLevel = ViewManager.MediaPlayer.VolumeLevel;
					ViewManager.MediaPlayer.OnClosing();
				}

				CoreHelper.SaveTraceBuffer();

				ShortcutKeyManager.SaveMappings();
				Configuration.SaveSettings();
				FeedRepository.SaveRepository();
				EnclosureDownloadHistory.SaveHistory();
				ItemReadHistory.SaveHistory();
			}
			catch (Exception ex)
			{
				CoreHelper.WriteLogEntry("Exception was thrown during application exit! Reason:" + ex);
			}
		}

		private static bool ExportLocationValidator(string input)
		{
			return !string.IsNullOrEmpty(input) && Directory.Exists(Path.GetDirectoryName(input));
		}

		#endregion

		#region Menu Commands

		public enum DownloadHistoryOperation
		{
			MarkAllPodcastsAsDownloaded,
			MarkAllPodcastsAsNotDownloaded
		}

		private static bool StartExternalPlayerFor(string path)
		{
			var myProcess = new Process();
			try
			{
				// Get the path that stores user documents.
				myProcess.StartInfo.FileName = path;
				myProcess.StartInfo.Verb = "Open";
				myProcess.StartInfo.UseShellExecute = true;
				myProcess.Start();
				return true;
			}
			catch (Win32Exception)
			{
				MessageBoxEx.Show(string.Format(Resources.UnsupportedFileTypeMessage, Path.GetExtension(path)),
				                  Resources.UnsupportedFileTypeTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation,
				                  MessageBoxDefaultButton.Button1);
			}

			return false;
		}

		public static void CmdStreamTrack(Track aTrack)
		{
			try
			{
				PlayerIntegration desiredPlayer = PlayerIntegration.UseExternalPlayerPlaylistPLS; // aTrack.ParentFeed.FeedPlayer;

				var streamPlaylist = new TrackList();
				streamPlaylist.Add(aTrack);
				string playlist = FeedRepository.GeneratePlaylistFor(streamPlaylist, aTrack, desiredPlayer);
				aTrack.TrackPath = playlist;

				if (desiredPlayer == PlayerIntegration.UseInternalPlayer)
				{
					ViewManager.MediaPlayer.PlayTracks(streamPlaylist, aTrack);
					CmdGoToView(Helpers.ViewNames.Player);
					ViewManager.RefreshTitle();
				}
				else
				{
					StartExternalPlayerFor(aTrack.TrackPath);
				}

				aTrack.ParentFeed.HasNewContent = false; //mark the feed as read
			}
			catch (Exception ex)
			{
				MessageBoxEx.Show(string.Format(Resources.PlaylistGenerationFailedMsg, ex.Message),
				                  Resources.PlaylistGenerationFailedTitle, MessageBoxButtons.OK,
				                  MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
			}
		}

		public static void CmdToggleTrackViewAll()
		{
			if (!ViewManager.Tracks.HasFeedFilter())
			{
				if (ViewManager.Feeds.SelectedFeed != null)
				{
					ViewManager.Tracks.SetFeedFilter(ViewManager.Feeds.SelectedFeed);
					Configuration.ShowAllPodcastsInCategory = false;
				}
			}
			else
			{
				ViewManager.Tracks.ClearFeedFilter();
				Configuration.ShowAllPodcastsInCategory = true;
			}
		}

		public static void CmdShowUpdateReport()
		{
			NavigateToPrivateExternalUrl(new Uri(Configuration.FeedUpdateLogFilePath), "Update Log");
		}

		public static void CmdShowHelp()
		{
			NavigateToPrivateExternalUrl(Configuration.HelpFilePath, "BeyondPod Help");
		}

		public static void CmdCheckForUpdates()
		{
			if (VersionCheckManager.VersionInfo.IsNewDevVersionAvailable && !VersionCheckManager.VersionInfo.IsNewPublicVersionAvailable)
				NavigateToPrivateExternalUrl(Configuration.VersionCheckBetaURL, "BeyondPod BETA");
			else
				NavigateToPrivateExternalUrl( Configuration.VersionCheckURL, "BeyondPod Updates");
		}

		public static void CmdOpenDonatePage()
		{
			NavigateToPrivateExternalUrl(Configuration.DonateURL, "Support Beyondpod");
		}

		public static void CmdOpenSuggestPage()
		{
			NavigateToPrivateExternalUrl(Configuration.SuggestFeatureURL, "Suggest Feature");
		}

		private static void NavigateToFeedContentView()
		{
			if (ViewManager.FeedContent.CurrentFeed != null)
				CmdGoToView(Helpers.ViewNames.FeedContent);
			else
				Helpers.Beep();
		}

		private static void NavigateToPrivateExternalUrl(Uri url, string name)
		{
			ViewManager.CurrentViewName = Helpers.ViewNames.FeedContent;
			ViewManager.FeedContent.SetExternalURL(url, name);
		}

		public static void NavigateToPublicExternalUrl(Uri url, string name)
		{
			//Check if we are configured to use an external browser
			if (!string.IsNullOrEmpty(Configuration.ExternalUrlHandler))
			{
				CmdExecuteCommandLine(Configuration.ExternalUrlHandler.Replace("%1", url.ToString()));
			}
			else
			{
				ViewManager.CurrentViewName = Helpers.ViewNames.WebBrowser;
				ViewManager.WebBrowser.SetExternalURL(url, name);
			}
		}

		/// <summary>
		/// Opens the selected feed.
		/// </summary>
		public static void CmdViewSelectedFeedPodcasts()
		{
			Feed aFeed = ViewManager.Feeds.SelectedFeed;

			if (aFeed != null)
			{
				aFeed.ViewType = FeedViewType.Tracks;
				OpenDefaultFeedView(aFeed);
			}
			else
			{
				if(ViewManager.MediaPlayer.HasPlaylist)
					CmdGoToView(Helpers.ViewNames.Player);
			}
		}

		/// <summary>
		/// Plays the selected feed.
		/// </summary>
		public static void CmdPlaySelectedFeed()
		{
			Feed aFeed = ViewManager.Feeds.SelectedFeed;

			if (aFeed != null)
			{
				Track t = aFeed.Tracks.GetFirstUnplayedOrPartiallyPlayedTrack();
				if (t != null)
					PlayTrack(t);
			}
		}

		/// <summary>
		/// Activates a specific view.
		/// </summary>
		/// <param name="i_view">The i_view.</param>
		internal static void CmdGoToView(Helpers.ViewNames i_view)
		{
			ViewManager.CurrentViewName = i_view;
		}

		/// <summary>
		/// Deletes all played tracks.
		/// </summary>
		public static void CmdDeleteAllPlayedTracks()
		{
			FeedRepository.DeleteAllPlayedTracks(null);
		}

		/// <summary>
		/// Goes the back.
		/// </summary>
		internal static void CmdGoBack()
		{
			if (ViewManager.CurrentViewName == Helpers.ViewNames.Player)
				ViewManager.CurrentViewName = Helpers.ViewNames.Tracks;
			else if (ViewManager.CurrentViewName == Helpers.ViewNames.Tracks)
				if (ViewManager.Feeds.Feed != null)
					ViewManager.CurrentViewName = Helpers.ViewNames.Feeds;
				else if (ViewManager.MediaPlayer.HasPlaylist)
					ViewManager.CurrentViewName = Helpers.ViewNames.Player;
				else
					Helpers.Beep();
			else if (ViewManager.CurrentViewName == Helpers.ViewNames.Feeds)
			{
				if (ViewManager.Feeds.Feed != null && ViewManager.Feeds.Feed.ParentFeed != null)
					ViewManager.Feeds.SetRootFeed(ViewManager.Feeds.Feed.ParentFeed,ViewManager.Feeds.Feed);
				else if (ViewManager.MediaPlayer.HasPlaylist)
					ViewManager.CurrentViewName = Helpers.ViewNames.Player;
				else
					Helpers.Beep();
			}
			else if (ViewManager.CurrentViewName == Helpers.ViewNames.FeedContent)
			{
				if (ViewManager.FeedContent.IsShowingWebPage)
					ViewManager.FeedContent.NavigateBack();
					/*else if (ViewManager.FeedContent.CurrentFeed.Tracks.Count > 0)
					CmdToggleFeedView(ViewManager.FeedContent.CurrentFeed, FeedViewType.Tracks);*/
				else
					ViewManager.CurrentViewName = Helpers.ViewNames.Feeds;
			}
			else if (ViewManager.CurrentViewName == Helpers.ViewNames.WebBrowser)
			{
				ViewManager.WebBrowser.NavigateBack();
			}
		}

		/// <summary>
		/// Exits the application.
		/// </summary>
		internal static void CmdExitApplication()
		{
			Master.MasterForm.ForceApplicationExit = true;
			Master.MasterForm.CloseForm();
		}

		public static void CmdRefreshFeeds()
		{
			if (!FeedRepository.IsEmpty)
			{
				FeedRepository.Refresh();
			}
			else
				ViewManager.Feeds.Clear();
		}

		internal static void CmdShowSettingsForm()
		{
			var s = new Settings();
			s.ShowDialog();
			Application.DoEvents();
			if (s.ShouldReloadRepository)
			{
				CmdRefreshFeeds();
				ViewManager.Feeds.Reload();
				ViewManager.Tracks.Reload();
			}
		}

		internal static void CmdResetTrackPlayedStatus()
		{
			Track t = ViewManager.Tracks.SelectedTrack;
			if (t != null)
				t.ClearPlayed();

			ViewManager.Tracks.NotifyTrackStatusChanged(t);
		}

		internal static void CmdSetTrackPlayedStatus()
		{
			Track t = ViewManager.Tracks.SelectedTrack;
			if (t != null)
				t.MarkPlayed();

			ViewManager.Tracks.NotifyTrackStatusChanged(t);
		}

		internal static void CmdToggleTrackPlayedStatus()
		{
			Track t = ViewManager.Tracks.SelectedTrack;
			if (t != null)
			{
				if (t.IsPlayed)
					t.ClearPlayed();
				else
					t.MarkPlayed();
			}

			ViewManager.Tracks.NotifyTrackStatusChanged(t);
		}

		internal static void CmdDeletePlayedInFeed()
		{
			FeedRepository.DeleteAllPlayedTracks(ViewManager.Tracks.GetFeedFilter());
		}

		internal static void CmdSwitchPlayerView(CoreHelper.PlayerView playerView)
		{
			ViewManager.MediaPlayer.ViewMode = playerView;
		}

		internal static void CmdGoToTheEndOfTrack()
		{
			if (ViewManager.MediaPlayer.CurrentTrack != null &&
			    ViewManager.MediaPlayer.CurrentTrack.TrackType == Track.StreamType.LocalFile)
			{
				//position at the end of the current stream
				ViewManager.MediaPlayer.CurrentStreamPosition = ViewManager.MediaPlayer.CurrentStreamDuration - 1;
			}
			else
				Helpers.Beep();
		}

		internal static void CmdPlayNextTrack()
		{
			ViewManager.MediaPlayer.SkipTrack(Helpers.MoveDirection.Forward);
		}

		internal static void CmdPlayPreviousTrack()
		{
			ViewManager.MediaPlayer.SkipTrack(Helpers.MoveDirection.Back);
		}

		internal static void CmdShowAboutScreen()
		{
			string wmpver = "N/A";

			if (ViewManager.MediaPlayer.IsPlayerLoaded)
				wmpver = ViewManager.MediaPlayer.PlayerVersion;

			string platform;

			if (PlatformDetection.IsSmartphone())
				platform = " (SP)";
			else
				platform = " (PPC)";

			string message =
				string.Format(Resources.AboutScreenMessage,
				              Configuration.ProductVersion,
				              Environment.Version,
				              Environment.OSVersion + platform,
				              wmpver,
				              CoreHelper.GetManagedMemoryUsedAsString(),
				              CoreHelper.GetTotalProcessMemoryUsedAsString());

			MessageBoxEx.Show(message,
			                  Resources.AboutScreenTitle, MessageBoxButtons.OK, MessageBoxIcon.Asterisk,
			                  MessageBoxDefaultButton.Button1);
		}

		public static void CmdPlayPause()
		{
			ViewManager.MediaPlayer.PlayPause();
		}

		public static void CmdPlay()
		{
			ViewManager.MediaPlayer.Play();
		}

		public static void CmdStop()
		{
			ViewManager.MediaPlayer.Stop();
		}

		public static void CmdPause()
		{
			ViewManager.MediaPlayer.Pause();
		}

		public static void CmdShortSkipForward()
		{
			ViewManager.MediaPlayer.SkipShort(Helpers.MoveDirection.Forward);
		}

		public static void CmdShortSkipBack()
		{
			ViewManager.MediaPlayer.SkipShort(Helpers.MoveDirection.Back);
		}

		public static void CmdLongSkipForward()
		{
			ViewManager.MediaPlayer.SkipLong(Helpers.MoveDirection.Forward);
		}

		public static void CmdLongSkipBack()
		{
			ViewManager.MediaPlayer.SkipLong(Helpers.MoveDirection.Back);
		}

		public static void CmdVolumeUp()
		{
			ViewManager.MediaPlayer.ChangeVolume(Helpers.MoveDirection.Forward);
		}

		public static void CmdVolumeDown()
		{
			ViewManager.MediaPlayer.ChangeVolume(Helpers.MoveDirection.Back);
		}

		internal static void CmdDeleteCurrentAndPlayNext()
		{
			Track old = ViewManager.MediaPlayer.CurrentTrack;

			Track t = ViewManager.MediaPlayer.GetNextPrevTrack(Helpers.MoveDirection.Forward);

			if (t != null)
			{
				ViewManager.MediaPlayer.PlayTrack(t);

				if (old.AllowAutoDelete)
					FeedRepository.DeleteTrack(old, true);
			}
			else
			{
				if (old.AllowAutoDelete)
					m_DelayedDeleter.DeleteTrack(old);

				if (ViewManager.CurrentViewName == Helpers.ViewNames.Player || ViewManager.CurrentViewName == Helpers.ViewNames.Tracks)
					CmdGoToView(Helpers.ViewNames.Feeds);
			}
		}

		internal static void CmdShowShortcutEditorForm()
		{
			var s = new ShortcutEditor();
			s.ShowDialog();
		}

		internal static void CmdShowFeedPropertiesDialog()
		{
			if (ViewManager.Feeds.SelectedFeed == null)
			{
				Helpers.Beep();
				return;
			}

			var f = new FeedProperties();
			f.CurrentFeed = ViewManager.Feeds.SelectedFeed;

			if (f.ShowDialog() == DialogResult.OK)
			{
				if (f.MustRefreshRepository)
					FeedRepository.Refresh();
				else
				{
					FeedRepository.SortTracks(ViewManager.Feeds.SelectedFeed);
				}

				if (ViewManager.Tracks.IsShowingFeed(ViewManager.Feeds.SelectedFeed))
				{
					ViewManager.Tracks.Reload();
				}

				ViewManager.Feeds.Reload();
			}
		}

		internal static void CmdDeleteFeed()
		{
			if (ViewManager.Feeds.SelectedFeed == null)
			{
				Helpers.Beep();
				return;
			}

			if (MessageBoxEx.Show(string.Format(Resources.ConfirmFeedDeleteMsg, ViewManager.Feeds.SelectedFeed.Name),
			                      Resources.ConfirmFeedDeleteTitle, MessageBoxButtons.OKCancel, MessageBoxIcon.Question,
			                      MessageBoxDefaultButton.Button2) ==
			    DialogResult.OK)
			{
				string downloadPath = null;
				if (ViewManager.Feeds.SelectedFeed.DownloadPathExists)
				{
					downloadPath = ViewManager.Feeds.SelectedFeed.FeedPath;
				}

				RssFeedCache.DeleteFeedCacheFor(ViewManager.Feeds.SelectedFeed);
				FeedImageCache.DeleteImageCacheFor(ViewManager.Feeds.SelectedFeed);
				ItemReadHistory.RemoveAllItemsFor(ViewManager.Feeds.SelectedFeed.ID);

				FeedRepository.DeleteFeed(ViewManager.Feeds.SelectedFeed);
				ViewManager.Feeds.Reload();
				FeedRepository.AutoSaveRepository();

				if (downloadPath != null)
				{
					if (MessageBoxEx.Show(Resources.ConfirmDeleteFeedDirectoryMsg,
					                      Resources.ConfirmDeleteFeedDirectoryTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question,
					                      MessageBoxDefaultButton.Button2) ==
					    DialogResult.Yes)
					{
						try
						{
							foreach (string file in Directory.GetFiles(downloadPath))
								File.Delete(file);

							Directory.Delete(downloadPath);
						}
						catch (Exception ex)
						{
							CoreHelper.WriteLogEntry("Unable to delete feed download directory! Reason: " + ex.Message);
							Helpers.Beep();
						}
					}
				}
			}
		}

		internal static void CmdAddFeed()
		{
			var f = new Feed(Guid.NewGuid(), FeedRepository.RootFeed);
			var fdlg = new FeedProperties();
			fdlg.CurrentFeed = f;

			if (fdlg.ShowDialog() == DialogResult.OK)
			{
				FeedRepository.RootFeed.Feeds.Add(f);
				FeedRepository.Refresh();
				ViewManager.Feeds.SelectedFeed = f;
				FeedRepository.AutoSaveRepository();
			}
		}

		public static void CmdOpenFeedBrowser(Feed i_Feed)
		{
			ViewManager.CurrentViewName = Helpers.ViewNames.FeedContent;
			ViewManager.FeedContent.CurrentFeed = i_Feed;
		}

		public static void CmdOpenExternalBrowser(string URL)
		{
			var myProcess = new Process();
			try
			{
				if (URL != null && URL.Trim().Length > 0)
				{
					myProcess.StartInfo.FileName = "iexplore.exe";
					myProcess.StartInfo.Arguments = URL;
					myProcess.StartInfo.Verb = "Open";
					myProcess.Start();
				}
			}
			catch (Win32Exception)
			{
				MessageBoxEx.Show(Resources.UnableToOpenFeedUrl,
				                  Resources.UnableToOpenFeedUrlTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation,
				                  MessageBoxDefaultButton.Button1);
			}
		}

		public static void CmdExecuteCommandLine(string commandLine)
		{
			var myProcess = new Process();
			try
			{
				if (commandLine != null && commandLine.Trim().Length > 0)
				{
					int i = commandLine.LastIndexOf(".exe", StringComparison.InvariantCultureIgnoreCase);
					if (i > 0 && i + 4 < commandLine.Length)
					{
						i += 4;

						if (commandLine.Substring(i, 1) == "\"")
							i++;

						myProcess.StartInfo.Arguments = commandLine.Substring(i).Trim();
						myProcess.StartInfo.FileName = commandLine.Substring(0, i);
					}
					else
					{
						myProcess.StartInfo.FileName = commandLine;
						myProcess.StartInfo.Verb = "Open";
					}

					myProcess.StartInfo.UseShellExecute = true;
					myProcess.Start();
				}
			}
			catch (Win32Exception)
			{
				MessageBoxEx.Show(Resources.UnableToOpenFeedUrl,
				                  Resources.UnableToOpenFeedUrlTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation,
				                  MessageBoxDefaultButton.Button1);
			}
		}


		public static void CmdExecuteCommandLine(string application, string parameters)
		{
			try
			{
				Process.Start(application, parameters);
			}
			catch (Win32Exception)
			{
				MessageBoxEx.Show(Resources.UnableToOpenFeedUrl,
													Resources.UnableToOpenFeedUrlTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation,
													MessageBoxDefaultButton.Button1);
			}
		}


		public static void CmdUpdateFeed()
		{
			if (ViewManager.FeedContent.IsUpdating)
				ViewManager.FeedContent.StopFeedUpdate();
			else
			{
				ViewManager.FeedContent.UpdateFeedContent(false);
			}
		}

		public static void CmdDeleteOldFeeds()
		{
			FeedRepository.DeleteOldTracks();
		}

		public static void CmdPauseResumeDownload()
		{
			if (UpdateAndDownloadManager.IsWorking)
				UpdateAndDownloadManager.TerminateAll();
			else if (EnclosureDownloadManager.IsDownloading)
				EnclosureDownloadManager.TerminateAllDownloads();
			else if (ViewManager.Tracks.SelectedTrack != null && !ViewManager.Tracks.SelectedTrack.IsFullyDownloaded)
				EnclosureDownloadManager.DownloadEnclosure(ViewManager.Tracks.SelectedTrack);
		}

		public static void CmdToggleFeedView(Feed feed, FeedViewType i_Type)
		{
			if (feed == null)
			{
				Helpers.Beep();
				return;
			}

			bool changed = false;

			if (i_Type == FeedViewType.Tracks)
			{
				if (feed.AllowEnclosures)
				{
					feed.ViewType = FeedViewType.Tracks;
					changed = true;
				}
			}

			if (i_Type == FeedViewType.RSS)
			{
				if (feed.HasUrl)
				{
					feed.ViewType = FeedViewType.RSS;
					changed = true;
				}
			}

			if (changed)
			{
				OpenDefaultFeedView(feed);
			}
			else
			{
				Helpers.Beep();
			}
		}

		public static void CmdOpenFeedUrl()
		{
			if (ViewManager.CurrentViewName == Helpers.ViewNames.Feeds)
			{
				if (ViewManager.Feeds.SelectedFeed != null)
				{
					CmdOpenFeedBrowser(ViewManager.Feeds.SelectedFeed);
				}
			}
			else if (ViewManager.CurrentViewName == Helpers.ViewNames.Tracks)
			{
				Feed feed = ViewManager.Tracks.SelectedTrack != null
				            	? ViewManager.Tracks.SelectedTrack.ParentFeed
				            	: ViewManager.Feeds.SelectedFeed;
				if (feed != null)
					CmdOpenFeedBrowser(feed);
			}
		}


		public static void CmdMarkClearDownloaded(Feed feed, DownloadHistoryOperation operation)
		{
			if (feed == null)
			{
				Helpers.Beep();
				return;
			}

			if (MessageBoxEx.Show(operation == DownloadHistoryOperation.MarkAllPodcastsAsNotDownloaded
			                      	?
			                      		Resources.ConfirmDeleteFeedHistoryMessage
			                      	:
			                      		Resources.ConfirmAddFeedHistoryMessage,
			                      operation == DownloadHistoryOperation.MarkAllPodcastsAsNotDownloaded
			                      	?
			                      		Resources.ConfirmDeleteFeedHistoryTitle
			                      	:
			                      		Resources.ConfirmAddFeedHistoryTitle,
			                      MessageBoxButtons.OKCancel,
			                      MessageBoxIcon.Question,
			                      MessageBoxDefaultButton.Button2) != DialogResult.OK)
			{
				return;
			}

			try
			{
				Cursor.Current = Cursors.WaitCursor;

				RssFeed f = null;

				try
				{
					f = RssFeedCache.LoadFromCache(ViewManager.Feeds.SelectedFeed);
				}
				catch
				{
					//just ignore - we logged in LoadFromCache
				}

				if (f == null)
				{
					MessageBoxEx.Show(Resources.RssFeedNotUpdatedMsg, Resources.RssFeedNotUpdatedTitle, MessageBoxButtons.OK,
					                  MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
					return;
				}

				if (operation == DownloadHistoryOperation.MarkAllPodcastsAsDownloaded)
					EnclosureDownloadHistory.AddAllEnclosures(f);
				else
					EnclosureDownloadHistory.RemoveAllEnclosuresForFeed(f);

				ViewManager.FeedContent.UpdateDownloadStaus(ViewManager.Feeds.SelectedFeed, null);
			}
			finally
			{
				Cursor.Current = Cursors.Default;
			}
		}

		public static void CmdStartBatchUpdate(Feed feed)
		{
			var toUpdate = new FeedList();

			if (feed.HasUrl)
				toUpdate.Add(feed);

			UpdateAndDownloadManager.StartUpdateDownload(toUpdate);
		}

		public static void CmdStartBatchUpdate(FeedCategory kind)
		{
			var toUpdate = new FeedList();

			foreach (Feed f in FeedRepository.RootFeed.Feeds)
			{
				if (f.HasUrl & (kind == CategoryManager.AllFeeds || f.Categories.IsOfCategory(kind)))
					toUpdate.Add(f);
			}

			UpdateAndDownloadManager.StartUpdateDownload(toUpdate);
		}

		public static void CmdStartBatchUpdateForFailedFeeds()
		{
			var toUpdate = new FeedList();

			foreach (Feed f in FeedRepository.RootFeed.Feeds)
			{
				if (f.HasUrl && (f.UpdateFailed || f.DownloadFailed))
					toUpdate.Add(f);
			}

			UpdateAndDownloadManager.StartUpdateDownload(toUpdate);
		}

		public static void CmdTerminateBatchUpdate()
		{
			if (UpdateAndDownloadManager.IsWorking)
				UpdateAndDownloadManager.TerminateAll();
			else if (RssFeedUpdateManager.IsUpdating)
				RssFeedUpdateManager.TerminateAllUpdates();
			else if (EnclosureDownloadManager.IsDownloading)
				EnclosureDownloadManager.TerminateAllDownloads();
		}

		public static void CmdFeedContentBrowserStop()
		{
			ViewManager.FeedContent.BrowserStop();
		}

		public static void CmdWebBrowserStop()
		{
			ViewManager.WebBrowser.BrowserStop();
		}

		internal static void CmdImportFeeds(Feed feed)
		{
			ViewManager.CurrentViewName = Helpers.ViewNames.Feeds;

			var o = new Opml();
			o.OpmlFeed = feed;
			o.ShowDialog();
		}

		internal static void CmdExportFeeds()
		{
			string exportFile = InputBoxEx.ShowInputBox("Export Feeds", "Export To", Configuration.ExportedOPMLPath,
			                                            "Enter a path and the name of to the exported file. (for example:\n \\My Documents\\BeyondPodFeeds.opml)",
			                                            ExportLocationValidator,
			                                            "The file name is empty or the destination folder does not exist!",
			                                            "Invalid Export File");

			if (string.IsNullOrEmpty(exportFile))
				return;

			try
			{
				FeedRepository.SaveRepositoryAsOpml(exportFile);
				Configuration.ExportedOPMLPath = exportFile;
			}
			catch
			{
				MessageBoxEx.Show(Resources.FailedToExportOpmlMsg, Resources.FailedToExportOpmlTitle, MessageBoxButtons.OK,
				                  MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
			}
		}

		public static void CmdClearFeedCache()
		{
			if (MessageBoxEx.Show(Resources.DeleteFeedCacheMsg, Resources.DeleteFeedCacheTitle, MessageBoxButtons.OKCancel,
			                      MessageBoxIcon.Question,
			                      MessageBoxDefaultButton.Button2) ==
			    DialogResult.OK)
			{
				RssFeedCache.DeleteCacheForAllFeeds();
				FeedImageCache.DeleteImageCacheForAllFeeds();
			}
		}

		public static void CmdDownloadApplicationUpdate(Uri url)
		{
			CmdOpenExternalBrowser(url.ToString());
			CmdExitApplication();
		}

		public static void CmdShowNextFeedContent(int i, bool unreadOnly)
		{
			Feed f;
			if (i > 0)
			{
				f = unreadOnly ? ViewManager.Feeds.GetNextUnreadFeed() : ViewManager.Feeds.GetNextFeed();
			}
			else
				f = ViewManager.Feeds.GetPreviousFeed();

			if (f != null && f.HasUrl)
			{
				ViewManager.Feeds.SelectedFeed = f;
				CmdOpenFeedBrowser(f);
			}
			else
				Helpers.Beep();
		}

		public static void CmdTurnBacklightOff()
		{
			CoreHelper.SetDevicePowerState(CoreHelper.PowerState.UserIdle);
		}

		public static void CmdMarkAllFeedItemsAsRead(RssFeed rss)
		{
			if (rss == null)
			{
				Helpers.Beep();
				return;
			}

			rss.SetAllItemsAsRead();
			ViewManager.FeedContent.BrowserRefresh();
		}

		public static void CmdTogglePlaylist()
		{
			if(ViewManager.CurrentViewName == Helpers.ViewNames.Player)
				CmdGoToView(Helpers.ViewNames.Tracks);
			else if(ViewManager.CurrentViewName == Helpers.ViewNames.Tracks)
				CmdGoToView(Helpers.ViewNames.Player);
		}

		public static void CmdRefreshFeedContent()
		{
			if (ViewManager.FeedContent.CurrentFeed != null &&
					ViewManager.FeedContent.CurrentFeed.IsAggregate)
				ViewManager.FeedContent.UpdateFeedContent(false);
			else
				ViewManager.FeedContent.BrowserRefresh();
		}

		public static void CmdToggleGroupTracksByFeed()
		{
			Configuration.GroupByFeedIfShowingCategoryTracks = !Configuration.GroupByFeedIfShowingCategoryTracks;
			ViewManager.Tracks.Reload();
		}

		#endregion

		#region Common Commands

		internal static void DeleteSelectedTrack()
		{
			if (ViewManager.Tracks.SelectedTrack != null)
			{
				CmdDeleteTrack(ViewManager.Tracks.SelectedTrack);
			}
		}

		internal static void CmdDeleteTrack(Track t)
		{
			if (t != null)
			{
				FeedRepository.DeleteTrack(t, false);
			}
		}

		internal static void InitializeFeeds()
		{
			//There was no selected feed
			ViewManager.Feeds.SetRootFeed(FeedRepository.RootFeed, null); //There are sub feeds
			ViewManager.CurrentViewName = Helpers.ViewNames.Feeds;
		}

		public static void PlayTrack(Track i_Track)
		{
			if (ViewManager.Tracks.GetFeedFilter() != i_Track.ParentFeed)
				ViewManager.Tracks.SetFeedFilter(i_Track.ParentFeed);

			ViewManager.Tracks.SelectedTrack = i_Track;

			if (i_Track.ParentFeed.ParentFeed != null && !ViewManager.Feeds.Feed.Equals(i_Track.ParentFeed.ParentFeed))
			{
					ViewManager.Feeds.SetRootFeed(i_Track.ParentFeed.ParentFeed,i_Track.ParentFeed);
			}

			ViewManager.Tracks.PlaySelected();
		}

		public static void OpenDefaultFeedView(Feed aFeed)
		{
			if (aFeed == null)
			{
				Helpers.Beep();
				return;
			}

			if (aFeed.Feeds.Count != 0)
			{
				//The feed contains sub feeds
				ViewManager.Feeds.SetRootFeed(aFeed,null);
			}
			else
			{
				if (aFeed.HasUrl && !aFeed.AllowEnclosures)
				{
					//Only ContentView is available
					CmdOpenFeedUrl();
				}
				else
				{
					//either Content or Tracks views are possible - use the preference
					if (aFeed.HasUrl && aFeed.AllowEnclosures)
					{
						//Check the default
						if (aFeed.ViewType == FeedViewType.Tracks)
						{
							CmdOpenTracksView(aFeed);
						}
						else
						{
							CmdOpenFeedUrl();
						}
					}
					else
					{
						// Only tracks view is possible
						CmdOpenTracksView(aFeed);
					}
				}
			}
		}

		private static void CmdOpenTracksView(Feed aFeed)
		{
			if(Configuration.ShowAllPodcastsInCategory)
				ViewManager.Tracks.ClearFeedFilter();
			else
				ViewManager.Tracks.SetFeedFilter(aFeed);

			CmdGoToView(Helpers.ViewNames.Tracks);
		}

		public static void CmdProcessExternalMessage(int wParam, string data)
		{
			CmdStartBatchUpdate(Helpers.GetScheduledUpdateCategoryForTaskNumber(wParam));
		}

		#endregion
	}
}